//
// Created by root on 10/26/22.
//

#ifndef TENCENT_BASE_H
#define TENCENT_BASE_H

#include <memory>
#include <cmath>
#include <vector>


namespace tencent {


    enum class LogLevel {
        VERBOSE = 0,
        DEBUG = 1,
        INFO = 2,
        WARNING = 3,
        ERROR = 4,
        FATAL = 5
    };


    class LoggerConfig {
    private:
        bool openLog_ = false;//true: open log; false: close log
        LogLevel minLoglevel_ = LogLevel::ERROR;
        bool saveToFile_ = false;//true: saved to file; false: print to console
    public :
        ~LoggerConfig() = default;

        LoggerConfig() = default;

        LoggerConfig(const LoggerConfig& config) {
            openLog_ = config.openLog_;
            minLoglevel_ = config.minLoglevel_;
            saveToFile_ = config.saveToFile_;
        }
        // 显式添加移动操作
        LoggerConfig(LoggerConfig&&) noexcept = default;             // 移动构造函数
        LoggerConfig& operator=(LoggerConfig&&) noexcept = default;  // 移动赋值运算符
        LoggerConfig(bool openLog, bool saveToFile, LogLevel minLoglevel){
            openLog_ = openLog;
            minLoglevel_ = minLoglevel;
            saveToFile_ = saveToFile;
        }
        bool isOpenLog() const {
            return openLog_;
        }

        void setOpenLog(bool openLog) {
            openLog_ = openLog;
        }

        bool isSaveToFile() const {
            return saveToFile_;
        }

        void setSaveToFile(bool saveToFile) {
            saveToFile_ = saveToFile;
        }

        LogLevel getMinLogLevel() const {
            return minLoglevel_;
        }

        void setMinLogLevel(LogLevel minLoglevel) {
            minLoglevel_ = minLoglevel;
        }

    };


    /**
     *
     * 数据模式
     */
    enum class Environment {
        /**
         * 正式环境
         */
        kProduct = 0,
        /**
         * 预发布环境
         */
        kPreProd = 1,
        /**
         * 开发环境
         */
        kDev = 2,
        /**
         * 测试环境
         */
        kTest = 3
    };


    class TaskCallback {
    public:
        virtual ~TaskCallback() {}

    public:
        /**
         * @brief 成功的回调
         *
         * @param taskTag 任务标识
         * @return
         */
        virtual void OnSuccess(const std::string taskTag) = 0;

        /**
         * @brief 任务执行失败的回调
         *
         * @param taskTag 任务标识
         * @param errCode 错误码
         * @param errMsg 错误原因
         * @return
         */
        virtual void OnError(const std::string taskTag, const int32_t errCode, const std::string errMsg) = 0;
    };

    template <typename T>
    class TaskResultCallback {
    public:
        virtual ~TaskResultCallback() {}

    public:
        /**
         * @brief 
         *
         * @param taskTag  
         * @param result  
         * @return
         */
        virtual void OnSuccess(const std::string taskTag, const T &result) = 0;

        /**
         * @brief   
         *
         * @param taskTag  
         * @param errorCode 
         * @return
         */
        virtual void OnError(const std::string taskTag, const int32_t errCode, const std::string errMsg) = 0;
    };
    
    class InitCallback {
    public:
        virtual ~InitCallback() {}

    public:
        /**
         * @brief init成功的回调
         *
         * @param 文件名
         * @return
         */
        virtual void OnSuccess() = 0;

        /**
         * @brief init失败的回调
         *
         * @param fileName 文件名
         * @param errCode 错误码
         * @param errMsg 错误原因
         * @return
         */
        virtual void OnError(const int32_t errCode, const std::string errMsg) = 0;
    };
    
    class UploadTaskCallback {
    public:
        virtual ~UploadTaskCallback() {}

        /**
         * @brief 成功的回调
         *
         * @param 文件名
         * @return
         */
        virtual void OnSuccess(const std::string fileName) = 0;

        /**
         * @brief 任务执行失败的回调
         *
         * @param fileName 文件名
         * @param errCode 错误码
         * @param errMsg 错误原因
         * @return
         */
        virtual void OnError(const std::string fileName, const int32_t errCode, const std::string errMsg) = 0;
    };

    class DataTransferCallback{
    public :
        virtual ~DataTransferCallback() {}
        /**
         * @brief 上传/下载字节数发生变化
         * @param nowUploadBytes 当前上传字节数
         * @param nowDownloadBytes 当前下载字节数
         */
         virtual void onTransferDataUpdated(const long long nowUploadBytes, const long long nowDownloadBytes) = 0;
    };

    class GeoItem {
    public:
        GeoItem() = default;

        ~GeoItem() = default;

        GeoItem(double_t lng, double_t lat, int64_t timestamp, float_t speed) : lng(lng), lat(lat),
                                                                                timestamp(timestamp), speed(speed) {}

        double_t lng = 0;
        double_t lat = 0;
        int64_t timestamp = 0;//ms, 毫秒
        float_t speed = 0;//m/s, 可不传

    };

    class GeoDataParam {
    public:
        std::vector<GeoItem> points;

        GeoDataParam() = default;

        ~GeoDataParam() = default;

        GeoDataParam(const std::vector<GeoItem> &points) : points(points) {}
    };


}
namespace TMDS {
    enum class TargetObjectType: int32_t {
        TargetObjectType_None = 0,
        TargetObjectType_Face = 1,
        TargetObjectType_License_Plate = 2,
    };

    class Box2d {
    public:
        Box2d() = default;

        ~Box2d() = default;

        Box2d(double x1, double y1, double width, double height);

        double x1() const;

        double y1() const;

        double width() const;

        double height() const;

        double x2() const;

        double y2() const;

    private:
        double x1_{-1.F};
        double y1_{-1.F};
        double width_{-1.F};
        double height_{-1.F};
        double x2_{-1.F};
        double y2_{-1.F};
    };

    class TargetObject {
    public:
        TargetObject() = default;

        ~TargetObject() = default;

        TargetObjectType type() const;

        Box2d box2d() const;

        void type(const TargetObjectType &type);

        void box2d(const Box2d &box2d);

    private:
        TargetObjectType type_ = TargetObjectType::TargetObjectType_None;
        Box2d box2d_;
    };
}


#endif //TENCENT_BASE_H
